suspend/resume now works again, though netfront contains a workaround hack for a xend issue.
static unsigned long sg_next_sect;
#define DISABLE_SCATTERGATHER() (sg_operation = -1)
+
+inline void translate_req_to_pfn( blkif_request_t * xreq, blkif_request_t * req)
+{
+ int i;
+
+ *xreq=*req;
+ for ( i=0; i<req->nr_segments; i++ )
+ {
+ xreq->frame_and_sects[i] = (req->frame_and_sects[i] & ~PAGE_MASK) |
+ (machine_to_phys_mapping[req->frame_and_sects[i]>>PAGE_SHIFT]<<PAGE_SHIFT);
+ }
+ return xreq;
+}
+
+inline void translate_req_to_mfn( blkif_request_t * xreq, blkif_request_t * req)
+{
+ int i;
+
+ *xreq=*req;
+ for ( i=0; i<req->nr_segments; i++ )
+ {
+ xreq->frame_and_sects[i] = (req->frame_and_sects[i] & ~PAGE_MASK) |
+ (phys_to_machine_mapping[req->frame_and_sects[i]>>PAGE_SHIFT]<<PAGE_SHIFT);
+ }
+ return xreq;
+}
+
+
static inline void flush_requests(void)
{
DISABLE_SCATTERGATHER();
DISABLE_SCATTERGATHER();
/* Update the copy of the request in the recovery ring. */
- blk_ring_rec->ring[MASK_BLKIF_IDX(blk_ring_rec->req_prod - 1)].req
- = *req;
+ translate_req_to_pfn(&blk_ring_rec->ring[
+ MASK_BLKIF_IDX(blk_ring_rec->req_prod - 1)].req, req);
return 0;
}
req->frame_and_sects[0] = buffer_ma | (fsect<<3) | lsect;
req_prod++;
- /* Keep a private copy so we can reissue requests when recovering. */
- blk_ring_rec->ring[MASK_BLKIF_IDX(blk_ring_rec->req_prod)].req = *req;
+ /* Keep a private copy so we can reissue requests when recovering. */
+ translate_req_to_pfn(&blk_ring_rec->ring[
+ MASK_BLKIF_IDX(blk_ring_rec->req_prod)].req, req);
blk_ring_rec->req_prod++;
return 0;
}
DISABLE_SCATTERGATHER();
- memcpy(&blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req, req, sizeof(*req));
- memcpy(&blk_ring_rec->ring[MASK_BLKIF_IDX(blk_ring_rec->req_prod++)].req,
- req, sizeof(*req));
+ blk_ring->ring[MASK_BLKIF_IDX(req_prod)].req = *req;
+
+ translate_req_to_pfn(&blk_ring_rec->ring[
+ MASK_BLKIF_IDX(blk_ring_rec->req_prod++)].req,req);
+
req_prod++;
flush_requests();
if ( recovery )
{
- int i;
+ int i,j;
/* Shouldn't need the io_request_lock here - the device is
* plugged and the recovery flag prevents the interrupt handler
for ( i = 0;
resp_cons_rec < blk_ring_rec->req_prod;
resp_cons_rec++, i++ )
- {
- blk_ring->ring[i].req
- = blk_ring_rec->ring[MASK_BLKIF_IDX(resp_cons_rec)].req;
+ {
+ translate_req_to_mfn(&blk_ring->ring[i].req,
+ &blk_ring_rec->ring[
+ MASK_BLKIF_IDX(resp_cons_rec)].req);
}
- /* Reset the private block ring to match the new ring. */
- memcpy(blk_ring_rec, blk_ring, sizeof(*blk_ring));
+ /* Reset the private block ring to match the new ring. */
+ for( j=0; j<i; j++ )
+ {
+ translate_req_to_pfn(
+ &blk_ring_rec->ring[j].req,
+ &blk_ring->ring[j].req);
+ }
+
resp_cons_rec = 0;
/* blk_ring->req_prod will be set when we flush_requests().*/
blk_ring_rec->req_prod = req_prod = i;
-
wmb();
/* Switch off recovery mode, using a memory barrier to ensure that
void blkdev_resume(void)
{
ctrl_msg_t cmsg;
- blkif_fe_driver_status_changed_t st;
-
+ blkif_fe_driver_status_changed_t st;
/* Send a driver-UP notification to the domain controller. */
cmsg.type = CMSG_BLKIF_FE;
static void __do_suspend(void)
{
+ int i,j;
/* Hmmm... a cleaner interface to suspend/resume blkdevs would be nice. */
extern void blkdev_suspend(void);
extern void blkdev_resume(void);
- extern void netif_resume(void);
-
+ extern void netif_suspend(void);
+ extern void netif_resume(void);
extern void time_suspend(void);
extern void time_resume(void);
suspend_record->nr_pfns = max_pfn; /* final number of pfns */
- //netdev_suspend();
- //blkdev_suspend();
-
__cli();
+ netif_suspend();
+
+ blkdev_suspend();
+
time_suspend();
ctrl_if_suspend();
memset(empty_zero_page, 0, PAGE_SIZE);
+ for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
+ {
+ pfn_to_mfn_frame_list[j] =
+ virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
+ }
+ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
+ virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
+
+
irq_resume();
ctrl_if_resume();
time_resume();
- __sti();
-
blkdev_resume();
+
netif_resume();
+ __sti();
+
+
out:
if ( suspend_record != NULL )
free_page((unsigned long)suspend_record);
netif->status = CONNECTED;
netif_get(netif);
+ netif->tx->resp_prod = netif->rx->resp_prod = 0;
+
rtnl_lock();
(void)dev_open(netif->dev);
rtnl_unlock();
/* Step 1: Reinitialise variables. */
np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0;
- np->rx->event = 1;
+ np->rx->event = np->tx->event = 1;
/* Step 2: Rebuild the RX and TX ring contents.
* NB. We could just free the queued TX packets now but we hope
* Initialize the network control interface. Set the number of network devices
* and create them.
*/
+
static void netif_driver_status_change(
netif_fe_driver_status_changed_t *status)
{
int err = 0;
int i;
-
+
netctrl.interface_n = status->nr_interfaces;
netctrl.connected_n = 0;
return err;
}
+void netif_suspend(void)
+{
+#if 1 /* XXX THIS IS TEMPORARY */
+ struct net_device *dev = NULL;
+ struct net_private *np = NULL;
+ int i;
+
+/* avoid having tx/rx stuff happen until we're ready */
+
+ for(i=0;i<netctrl.interface_n;i++)
+ {
+ char name[32];
+
+ sprintf(name,"eth%d",i);
+ dev = __dev_get_by_name(name);
+
+ if ( dev && (dev->flags & IFF_UP) )
+ {
+ np = dev->priv;
+
+ free_irq(np->irq, dev);
+ unbind_evtchn_from_irq(np->evtchn);
+ }
+ }
+#endif
+}
+
void netif_resume(void)
{
ctrl_msg_t cmsg;
- netif_fe_driver_status_changed_t st;
+ netif_fe_interface_connect_t up;
+// netif_fe_driver_status_changed_t st;
+ struct net_device *dev = NULL;
+ struct net_private *np = NULL;
+ int i;
+
+#if 1
+ /* XXX THIS IS TEMPORARY */
+
+ for(i=0;i<netctrl.interface_n;i++)
+ {
+ char name[32];
+ sprintf(name,"eth%d",i);
+ dev = __dev_get_by_name(name);
+
+ if ( dev ) // connect regardless of whether IFF_UP flag set
+ {
+ np = dev->priv;
+
+ // stop bad things from happening until we're back up
+ np->backend_state = BEST_DISCONNECTED;
+
+ cmsg.type = CMSG_NETIF_FE;
+ cmsg.subtype = CMSG_NETIF_FE_INTERFACE_CONNECT;
+ cmsg.length = sizeof(netif_fe_interface_connect_t);
+ up.handle = np->handle;
+ up.tx_shmem_frame = virt_to_machine(np->tx) >> PAGE_SHIFT;
+ up.rx_shmem_frame = virt_to_machine(np->rx) >> PAGE_SHIFT;
+ memcpy(cmsg.msg, &up, sizeof(up));
+
+ /* Tell the controller to bring up the interface. */
+ ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+ }
+ }
+#endif
+
+
+#if 0
/* Send a driver-UP notification to the domain controller. */
cmsg.type = CMSG_NETIF_FE;
cmsg.subtype = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED;
st.nr_interfaces = 0;
memcpy(cmsg.msg, &st, sizeof(st));
ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+#endif
+
}